package org.ice4apps.talk.session.security;

import javax.servlet.sip.*;
import org.apache.commons.lang.RandomStringUtils;

import org.ice4apps.util.IceLog;
import org.ice4apps.util.Util;

/**
 * @author biju
 * This class will challenge the request, if there is no Authorization header in the request.
 * If there is an Authorisation header, this class will verify the response and send the appropriate 
 * resposne back. 
 */

public class IceTalkAuthentication {
	
	static private IceTalkAuthentication _instance = null;

    static public IceTalkAuthentication instance() {
	      if(null == _instance) {
	         _instance = new IceTalkAuthentication();
	      }
	      return _instance;
	   }

	public SipServletResponse authenticate(SipServletRequest request) {
		String auth = request.getHeader("Authorization");
		if(auth != null) {
			String[] tokens = auth.split(",");
			
			String algorithm = null;
            String username_value = null;
            String realm_value = null;
            String passwd = null;
            String nonce_value = null;
            String nc_value = "00000001";
            String cnonce_value = null;
            String method = request.getMethod();
            String digest_uri_value = null;
            String entity_body = null;
            String qop_value = null;
            String response_value = null;
            
			for (int i=0; i<tokens.length; i++)
			{
				String[] nameValue = tokens[i].split("=");
				String name = nameValue[0].toLowerCase();
				String value = (nameValue[1].trim()).replaceAll("\"", "");
				
				if (name.contains("username"))
				{
					username_value = value;
					// TODO: Get the user password and domain from the DB
					// If the user doesn't exist send a 403
					passwd = "password";
				}
				else if (name.contains("realm"))
				{
					realm_value = value;
				}
				else if (name.contains("nonce"))
				{
					nonce_value = value;
				}
				else if (name.contains("uri"))
				{	
					digest_uri_value = value;
				}	
				else if (name.contains("response"))
				{
					response_value = value;
				}
				else if (name.contains("algorithm"))
				{
					algorithm = value;
				}
				else if (name.contains("nc"))
				{
					nc_value = value;
				}
				else if (name.contains("cnonce"))
				{
					cnonce_value = value;
				}
			}
			String response = MessageDigestResponseAlgorithm.calculateResponse(algorithm, username_value, realm_value, passwd, nonce_value, nc_value, cnonce_value, method, digest_uri_value, entity_body, qop_value);
			
			if(response_value.equals(response))
			{
				int successResponse = SipServletResponse.SC_OK;
				SipServletResponse resp = request.createResponse(successResponse);

				IceLog.info(this.getClass(), "Authentication Successful");
				return resp;
			}
			else
			{
				int errorResponse = SipServletResponse.SC_FORBIDDEN;
				SipServletResponse errorResp = request.createResponse(errorResponse);
				
				IceLog.info(this.getClass(), "Authentication Failiure. Request Forbidden");
				return errorResp;
			}
		}
		
		IceLog.info(this.getClass(), "Challenging Registration");
		int errorResponse = SipServletResponse.SC_UNAUTHORIZED;
		SipServletResponse challengeResponse = request.createResponse(errorResponse);
		String realm = "Registered_Subscribers";

		String nonce = RandomStringUtils.randomAlphanumeric(28);
		String opaque = RandomStringUtils.randomAlphanumeric(8);
		
		challengeResponse.setHeader("WWW-Authenticate", " Digest realm=\"" + realm + "\",domain=\"sip:localhost\",nonce=\"" + nonce + "\",opaque=\"339a2887\",stale=FALSE,algorithm=MD5" );

		return challengeResponse;
	}
}